package com.yellowpage.white.util;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;

import org.apache.commons.codec.binary.Base64;


public class Util4Java {

	// 一下3个常量和类成员（random）用于 randomKey方法
	public final static int MIN_RANDOM_KEY_LENGTH=8;	// 最短key长度
	public final static int DEF_RANDOM_KEY_LENGTH=12;	// 默认key长度
	public final static int MAX_RANDOM_KEY_LENGTH=32;	// 最大key长度
	public final static char[] RANDOM_KEY_SIGN = {'.',':',';',',','`','~','!','@','#','$','^','&','*','_','+','|'};
	private static Random random = new Random(System.currentTimeMillis());	// 类成员，初始化一次

	/**
	 * 计算一个固定长度(12位)的随机key，并返回
	 * <br/>
	 * key由大小写英文字母，阿拉伯数字和特殊字符构成
	 * @return
	 */
	public static String randomKey( ){
		return randomKey(DEF_RANDOM_KEY_LENGTH);
	}

	/**
	 * 计算一个指定长度的随机key，并返回
	 * <br/>
	 * key由大小写英文字母，阿拉伯数字和特殊字符构成
	 * @return
	 */
	public static String randomKey( int randomKeyLength ){
		StringBuffer keys = new StringBuffer();

		// 指定key过短，使用最小key长度
		if( randomKeyLength<MIN_RANDOM_KEY_LENGTH ){
			randomKeyLength = MIN_RANDOM_KEY_LENGTH;
		}
		// 指定key过长，使用最大key长度
		if( randomKeyLength>MAX_RANDOM_KEY_LENGTH ){
			randomKeyLength = MAX_RANDOM_KEY_LENGTH;
		}

		int key = 0;
		for( int i=0; i<randomKeyLength; i++ ){
			key = Math.abs(random.nextInt());

			switch (key%5){
			case 0:		// 0:number (0-9)
				keys.append(key%10);
				break;
			case 1:		// 1:lowercase(a-z)
				keys.append((char)('a'+(key%26)));
				break;
			case 2:		// 2:uppercase(A-Z)
				keys.append((char)('A'+(key%26)));
				break;
			case 3:		// sign (.:;,`~!@#$^&*_+|)
				keys.append(RANDOM_KEY_SIGN[(key+7)%RANDOM_KEY_SIGN.length]);
				break;
			default:	// other: lowercase(a-z)
				keys.append((char)('a'+(key%26)));
				break;
			}
		}

		return keys.toString();
	}


	/**
	 * 统计源字符串中关键字的出现次数
	 * @param src	源字符串
	 * @param key	关键字
	 * @return	统计值
	 */
    public static int keyCount4Str(String src , String key) {
        int i = 0 ;
        int index = 0 ;
        int num = 0 ;
        while(index != -1) {
            index = src.indexOf(key,i) ;
            if(index != -1)
                num ++ ;
            i = index + key.length() ;
        }
        return num ;
    }

	/**
	 * 异常信息处理
	 * @param e 异常信息
	 * @return 处理结果
	 */
	public static String getExceptionInfo( Exception e ){

		ByteArrayOutputStream baOutputStream = new  ByteArrayOutputStream();
		PrintStream ps = new PrintStream(baOutputStream);

		e.printStackTrace(ps);
		return baOutputStream.toString();

	}
	/**
	 * 用MD5算法对明码进行加密。
	 * @param rawPassword
	 * @param salt
	 * @return
	 * @throws NoSuchAlgorithmException
	 */
	public static String encodePasswordByMD5(String rawPassword,String salt)throws NoSuchAlgorithmException{

			String saltPassword  = mergeRawpasswordAndSalt(rawPassword,salt);
			MessageDigest messageDigest = MessageDigest.getInstance("MD5");
			byte[] digest = messageDigest.digest(saltPassword.getBytes());
			return new String(Base64.encodeBase64(digest));


	}
	/**
	 *
	 * @param rawPassword
	 * @param salt
	 * @return
	 */
	private static String mergeRawpasswordAndSalt(String rawPassword,String salt){
		if(rawPassword == null){
			rawPassword = "";
		}
		if(salt == null || "".equals(salt)){
			return rawPassword;
		}
		return rawPassword+"{"+salt+"}";
	}
	/**
	 * 下面的程序是为了生成一个DES算法，该算法需先生成一个key，用该key进行加密和解密。
	 * 对该key是存储在该项目下的
	 */
	public static SecretKey getSecretKeyDES(){
		KeyGenerator generator = null;
		try{
			generator = KeyGenerator.getInstance("DES");
			generator.init(new SecureRandom("qwqwreeweiooeooocdjcnmkdsx,l.".getBytes()));
			return generator.generateKey();
		}catch(Exception e){
			e.printStackTrace();
		}finally{
			generator = null;
		}
		return null;


	}
	public static  String encodeStringDES(String encodeString){
		if(encodeString == null)return "";
		try{
			SecretKey secretKey =  getSecretKeyDES();
			if(secretKey != null){
				Cipher cipher = Cipher.getInstance("DES");
				cipher.init(Cipher.ENCRYPT_MODE,secretKey);
				byte[] cipherBytes = cipher.doFinal(encodeString.getBytes());
				return byte2hex(cipherBytes);
			}
		}catch(Exception e){
			e.printStackTrace();
		}
		return null;

	}

	public static String decodeStringDES(String decodeString){
		if(decodeString == null)return "";
		try{
			SecretKey secretKey  = getSecretKeyDES();
			if(secretKey != null){
				Cipher cipher = Cipher.getInstance("DES");
				cipher.init(Cipher.DECRYPT_MODE, secretKey);
				byte[] cipherBytes = cipher.doFinal(hex2byte(decodeString.getBytes()));
				return new String(cipherBytes);

			}
		}catch(Exception e){

		}
		return null;
	}

	public static String byte2hex(byte[] b) { //二行制转字符串
        String hs = "";
        String stmp = "";
        for (int n = 0; n < b.length; n++) {
            stmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
            if (stmp.length() == 1) {
                hs = hs + "0" + stmp;
            } else {
                hs = hs + stmp;
            }
//            if (n < b.length - 1) {
//                hs = hs;
//            }
        }
        return hs.toUpperCase();
    }

	public static byte[] hex2byte(byte[] b){
		if(b.length%2 != 0)
			throw new IllegalArgumentException("长度不是偶数");
		byte[] b2 = new byte[b.length/2];
		for(int n=0;n<b.length;n+=2){
			String item = new String(b,n,2);
			b2[n/2] = (byte)Integer.parseInt(item,16);
		}
		return b2;
	}

	/**
	 * 解析文件名称，返回文件名后缀
	 * @param fileName 文件名称
	 * @return 文件名后缀(小写)，没有后缀返回NULL
	 */
	public static String getFileSuffix( String fileName ){
		if( fileName!=null ){
			int lastPointPosition = fileName.lastIndexOf(".");
			if( lastPointPosition>=0 ){
				String suffix = fileName.substring(lastPointPosition+1);
//				if( suffix.isEmpty()==false ){
//					// 返回小写文件后缀
//					return  suffix.toLowerCase();
//				}
			}
		}
		// 无法解析文件名称后缀
		return null;
	}

    /**
     * 提供精确的小数位四舍五入处理。
     * @param v 需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double v,int scale){
        if(scale<0){
            throw new IllegalArgumentException(
                "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        BigDecimal one = new BigDecimal("1");
        return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
    }
    public static void main(String[]  args){
    	double returnValue=Util4Java.round(4.01467592592592591671518675866536796092987060546875,2);
    	System.out.println("one=1结果是  "+returnValue);
    }
}
